package com.symaster.common.util;

import com.alibaba.fastjson.JSONObject;
import com.symaster.common.ExceptionFactory;
import com.symaster.common.geom.entity.Point;
import com.symaster.common.geom.util.PointUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.font.FontDesignMetrics;

import java.awt.*;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.*;

/**
 * @author yinmiao
 * @date 2022-01-04 21:27
 */
public class CommonUtil {

    private static final Logger logger = LoggerFactory.getLogger(CommonUtil.class);

    public static void main(String[] args) throws IOException {


        Point point = new Point(125.152, 20.878);
        Point p2 = new Point(118.234, 19.522);

        System.out.println("PointUtil.dis(point, p2) = " + PointUtil.dis(point, p2));


        // _m202210251043();
    }

    public static int getId() {
        UUID idOne = UUID.randomUUID();
        String str = "" + idOne;
        int uid = str.hashCode();
        String filterStr = "" + uid;
        str = filterStr.replaceAll("-", "");
        return Integer.parseInt(str);
    }

    public static boolean in(Integer e, int... rs) {
        if (rs == null || rs.length == 0) {
            return true;
        }
        if (e == null) {
            return false;
        }
        for (int r : rs) {
            if (r == e) {
                return true;
            }
        }
        return false;
    }

    public static String getJarPath(Class<?> clazz) throws UnsupportedEncodingException {
        String jarPath = clazz.getProtectionDomain().getCodeSource().getLocation().getFile();
        jarPath = java.net.URLDecoder.decode(jarPath, "UTF-8");
        return jarPath;
    }

    public static boolean isWindows() {
        String osName = System.getProperty("os.name");
        return osName != null && osName.toLowerCase().contains("win");
    }

    public static Model getPomXmlModel() throws IOException, XmlPullParserException {
        MavenXpp3Reader reader = new MavenXpp3Reader();
        String basePath = Objects.requireNonNull(Thread.currentThread().getContextClassLoader().getResource("")).getPath();
        if (isWindows() && basePath.startsWith("/")) {
            basePath = basePath.substring(1);
        }
        if (basePath.contains("/target/")) {
            basePath = basePath.substring(0, basePath.lastIndexOf("/target/"));
        }
        return reader.read(new FileReader(basePath + "\\pom.xml"));
    }

    public static String getJarVersion(Class<?> clazz, String groupId, String artifactId) {

        /* 查看jar包里面pom.properties版本号 */
        try {
            URL url = new URL(String.format("jar:file:%s!/META-INF/maven/%s/%s/pom.properties", getJarPath(clazz), groupId, artifactId));
            InputStream inputStream = url.openStream();
            Properties properties = new Properties();
            properties.load(inputStream);
            return properties.getProperty("version");
        } catch (Exception e) {
            /* 开发过程中查看pom.xml版本号 */
            try {
                return getPomXmlModel().getVersion();
            } catch (IOException | XmlPullParserException ex) {
                throw new RuntimeException(ex);
            }
        }
    }

    public static double pxToMm(double px, double dpi) {
        return px / dpi * 25.4;
    }

    public static double mmToPx(double mm, double dpi) {
        return mm * dpi / 25.4;
    }

    /**
     * 属性校验
     *
     * @param obj     对象
     * @param ignores 忽略字段
     * @throws IllegalArgumentException 当未忽略字段为空将抛出该异常
     */
    public static void checkPropertiesNotNull(Object obj, String... ignores) {
        if (obj == null) {
            throw ExceptionFactory.getDefaultException("必要参数不能为空");
        }

        List<String> ignoreList = null;
        if (ignores != null) {
            ignoreList = Arrays.asList(ignores);
        }
        Field[] fields = obj.getClass().getDeclaredFields();
        try {
            for (Field field : fields) {
                field.setAccessible(true);
                if (ignoreList != null && ignoreList.contains(field.getName())) {
                    continue;
                }
                Object value = field.get(obj);
                if (ObjectUtils.isEmpty(value)) {
                    throw ExceptionFactory.getDefaultException(String.format("必要参数'%s'不能为空", field.getName()));
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public static String executeRequest(HttpRequestBase requestBase) throws IOException {
        return executeRequest(requestBase, StandardCharsets.UTF_8);
    }

    public static String executeRequest(HttpRequestBase requestBase, Charset charset) throws IOException {
        return executeRequest(requestBase, charset, 10 * 1000);
    }

    public static String executeRequest(HttpRequestBase requestBase, Charset charset, int timeout) throws IOException {
        requestBase.setHeader("Content-Type", "application/json");

        CloseableHttpClient httpclient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String body = null;

        try {
            httpclient = HttpClients.createDefault();

            RequestConfig.Builder custom = RequestConfig.custom()
                    .setConnectTimeout(timeout)
                    .setConnectionRequestTimeout(timeout)
                    .setSocketTimeout(timeout);

            requestBase.setConfig(custom.build());
            response = httpclient.execute(requestBase);
            entity = response.getEntity();
            if (entity != null) {
                body = EntityUtils.toString(entity, charset);
            }
        } finally {
            IOUtil.close(httpclient, response);
            EntityUtils.consume(entity);
        }
        return body;
    }

    /**
     * 解析返回集
     *
     * @param resultStr   {'code':100, 'message':'success', 'data':['Hello World']}
     * @param successCode 100
     * @return ['Hello World']
     * @throws RuntimeException 任何一步失败
     */
    public static String getResultDataStr(String resultStr, String successCode) {
        return getResultDataStr(resultStr, "code", "data", successCode);
    }

    public static String getResultDataStr(String resultStr, String codeKey, String dataKey, String successCode) {
        if (StringUtils.isEmpty(resultStr)) {
            throw new RuntimeException("StringUtils.isEmpty(resultStr) = true");
        }
        JSONObject resultJson = null;
        try {
            resultJson = JSONObject.parseObject(resultStr);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("返回集有误 " + resultStr);
        }
        if (resultJson == null) {
            throw new RuntimeException("JSONObject.parseObject(resultStr) = true");
        }
        if (!successCode.equals(resultJson.getString(codeKey))) {
            String message = resultJson.getString("message");
            if (StringUtils.isNotEmpty(message)) {
                throw ExceptionFactory.getDefaultException(message);
            }
            throw new RuntimeException(String.format("'%s'.equals(resultJson.getString('code')) = false; %s", successCode, resultStr));
        }
        return resultJson.getString(dataKey);
    }

    /**
     * 根据字体计算文本宽度
     */
    public static int stringWidth(Font font, String text) {
        FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
        return metrics.stringWidth(text);
    }
}
